home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 151-175 / scopedisk170 / pcx2iff / pcxtoiff.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  8KB  |  327 lines

  1. /* PCXtoIFF.c - Converts IBM .PCX picture files to IFF format
  2.  *
  3.  * Written by David Godshall
  4.  * Released into the Public Domain by David Godshall
  5.  *
  6.  * This little utility was written as the request of another BBS caller who
  7.  * wanted to be able to view IBM .PCX type graphic files on his Amiga.  He
  8.  * uploaded the source to an IBM .PCX viewer which I used to determine the
  9.  * format of PCX files in order to be able to write this.  I was going to
  10.  * write a PCX viewer, but decided it would be better to be able to convert
  11.  * PCX files to IFF so more could be done with them then just viewing.
  12.  */
  13.  
  14. #include <exec/types.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17.  
  18. #define COMPRESS 1         /* Remove this line to disable compression */
  19.  
  20. typedef struct {
  21.    UBYTE red, green, blue;
  22. } TRIPLET;
  23.  
  24. typedef struct {              /* 128 byte header in PCX files */
  25.    UBYTE maker;               /* ??? */
  26.     UBYTE version;             /* PCX version */
  27.    UBYTE code;                /* ??? */
  28.    UBYTE bpp;                 /* ??? */
  29.    WORD  x1,y1;               /* Top, Left corner */
  30.    WORD  x2,y2;               /* Bottom, Right corner */
  31.    WORD  hres, vres;          /* Dots-Per-Inch */
  32.    TRIPLET triple[16];        /* palette */
  33.    UBYTE vmode;               /* ??? */
  34.    UBYTE nplanes;             /* Number of bitplanes */
  35.    UWORD bpl;                 /* Number of bytes per row */
  36.    UBYTE pad[128-68];
  37. } PCXHDR;
  38.  
  39. UBYTE Buffer[1024];
  40. int WriteSize,BodyPosition,BodySize;
  41.  
  42. PCXHDR PCXHeader;
  43. int PCXWide,PCXHigh,PCXDeep,PCX_BPL,IFF_BPL;
  44.  
  45. #define SwapWord(x) ((x) = ((x) & 0x00FF)<<8 | ((x) & 0xFF00)>>8)
  46.  
  47.  
  48. UBYTE ReadByte(fin)
  49.  
  50. FILE *fin;
  51. {
  52.    UBYTE data;
  53.    
  54.    if (fread((char *)&data,1,1,fin) != 1)
  55.    {
  56.       printf ("%% Error reading PCX file\n");
  57.       exit(20);
  58.    }
  59.    return data;
  60. }
  61.  
  62.  
  63. void WriteLong(fout,data)
  64.  
  65. FILE *fout;
  66. ULONG data;
  67. {
  68.    if (fwrite((char *)&data,4,1,fout) != 1)
  69.    {
  70.       printf ("%% Error writing IFF file\n");
  71.       exit(20);
  72.    }
  73.    WriteSize += 4;
  74. }
  75.  
  76.  
  77. void WriteWord(fout,data)
  78.  
  79. FILE *fout;
  80. UWORD data;
  81. {
  82.    if (fwrite((char *)&data,2,1,fout) != 1)
  83.    {
  84.       printf ("%% Error writing IFF file\n");
  85.       exit(20);
  86.    }
  87.    WriteSize += 2;
  88. }
  89.  
  90.  
  91. void WriteByte(fout,data)
  92.  
  93. FILE *fout;
  94. UBYTE data;
  95. {
  96.    if (fwrite((char *)&data,1,1,fout) != 1)
  97.    {
  98.       printf ("%% Error writing IFF file\n");
  99.       exit(20);
  100.    }
  101.    WriteSize += 1;
  102. }
  103.  
  104.  
  105. void WriteData(fout,data,size)
  106.  
  107. FILE *fout;
  108. APTR data;
  109. int size;
  110. {
  111.    if (fwrite((char *)data,size,1,fout) != 1)
  112.    {
  113.       printf ("%% Error writing IFF file\n");
  114.       exit(20);
  115.    }
  116.    WriteSize += size;
  117. }
  118.  
  119.  
  120. void WriteIFFRow(fout,data,size)
  121.  
  122. FILE *fout;
  123. UBYTE *data;
  124. int size;
  125. {
  126. #ifdef COMPRESS
  127.    UBYTE *ptr,*maxptr;
  128.    UBYTE ob,b;
  129.    int len,pos;
  130.    
  131.    pos = WriteSize;
  132.    ptr = data;
  133.    maxptr = data+size;
  134.    ob = *ptr++;
  135.    while (data < maxptr)
  136.    {
  137.       b = *ptr++;
  138.       while (b == ob && ptr < maxptr)
  139.          b = *ptr++;
  140.       len = ptr - data;
  141.       if (ptr < maxptr)
  142.          len--;
  143.       while (len >= 128)
  144.       {
  145.          WriteByte(fout,257-128);
  146.          WriteByte(fout,ob);
  147.          len -= 128;
  148.          data += 128;
  149.       }
  150.       if (len > 2)
  151.       {
  152.          WriteByte(fout,257-len);
  153.          WriteByte(fout,ob);
  154.          data += len;
  155.       }
  156.       else
  157.       {
  158.          ob = *data;
  159.          while (ptr < maxptr)
  160.          {
  161.             if (b != ob)
  162.             {
  163.                ob = b;
  164.                b = *ptr++;
  165.             }
  166.             else
  167.                if (ptr+1 < maxptr)
  168.                {
  169.                   if (*ptr == b)
  170.                      break;
  171.                   ob = b;
  172.                   b = *ptr++;
  173.                }
  174.                else
  175.                   break;
  176.          }
  177.          len = ptr-data-1;
  178.          if (ptr < maxptr)
  179.             len--;
  180.          while (len > 128)
  181.          {
  182.             WriteByte(fout,127);
  183.             WriteData(fout,data,128);
  184.             len -= 128;
  185.             data += 128;
  186.          }
  187.          if (len > 0)
  188.          {
  189.             WriteByte(fout,len-1);
  190.             WriteData(fout,data,len);
  191.             data += len;
  192.          }
  193.       }
  194.       ob = *data;
  195.    }
  196. /* if (WriteSize-pos & 1)
  197.       WriteByte(fout,0);  */
  198. #else
  199.    WriteData(fout,data,size);
  200. #endif
  201. }
  202.  
  203.  
  204. int main(argc,argv)
  205.  
  206. int argc;
  207. char *argv[];
  208. {
  209.    FILE *fin,*fout;
  210.    int x,y,n,b;
  211.    int AllRows,oldperc,newperc;
  212.    UBYTE *ptr;
  213.  
  214.    if (argc == 3)
  215.    {
  216.       fin = fopen(argv[1],"r");
  217.       if (fin)
  218.       {
  219.          if (fread((char *)&PCXHeader,1,128,fin) == 128)
  220.          {
  221.             PCXWide  = SwapWord(PCXHeader.x2)+1;
  222.             PCXHigh  = SwapWord(PCXHeader.y2)+1;
  223.             PCXWide -= SwapWord(PCXHeader.x1);
  224.             PCXHigh -= SwapWord(PCXHeader.y1);
  225.             SwapWord(PCXHeader.hres);
  226.             SwapWord(PCXHeader.vres);
  227.             PCX_BPL  = SwapWord(PCXHeader.bpl);
  228.             IFF_BPL  = PCX_BPL;
  229.             if (IFF_BPL & 1)
  230.                IFF_BPL++;
  231.             PCXDeep  = PCXHeader.nplanes;
  232.  
  233.             printf ("Converting %dx%dx%d from PCX to IFF... ",PCXWide,PCXHigh,PCXDeep);
  234.  
  235.             fout = fopen(argv[2],"w");
  236.             if (fout)
  237.             {
  238.                WriteSize = 0;
  239.                WriteData(fout,"FORM    ILBMBMHD",16);
  240.                WriteLong(fout,20);
  241.                WriteWord(fout,PCXWide);         /* Width */
  242.                WriteWord(fout,PCXHigh);         /* Height */
  243.                WriteWord(fout,PCXHeader.x1);    /* Xoffset */
  244.                WriteWord(fout,PCXHeader.y1);    /* Yoffset */
  245.                WriteByte(fout,PCXDeep);         /* Depth */
  246.                WriteByte(fout,0);               /* Masking */
  247. #ifdef COMPRESS
  248.                WriteByte(fout,1);               /* Compression on */
  249. #else
  250.                WriteByte(fout,0);               /* Compression off */
  251. #endif
  252.                WriteByte(fout,0);               /* pad */
  253.                WriteWord(fout,0);               /* Transparent Color */
  254.                WriteByte(fout,10);              /* XAspect, YAspect */
  255.                WriteByte(fout,PCXHeader.hres*10 / PCXHeader.vres);
  256.                WriteWord(fout,PCXWide);         /* PageWidth */
  257.                WriteWord(fout,PCXHigh);         /* PageHeight */
  258.                WriteData(fout,"CMAP",4);
  259.                WriteLong(fout,(1<<PCXDeep)*3);
  260.                WriteData(fout,&PCXHeader.triple,(1<<PCXDeep)*3);
  261.                WriteData(fout,"BODY    ",8);
  262.                BodyPosition = WriteSize-4;
  263.  
  264.                AllRows = PCXHigh*PCXDeep;
  265.                n = 0;
  266.                ptr = Buffer;
  267.                oldperc = -1;
  268.                for (y=0; y<AllRows; y++)
  269.                {
  270.                   newperc = (y*100)/AllRows;
  271.                   if (newperc != oldperc)
  272.                      printf ("%3d%%\b\b\b\b",newperc);
  273.                   oldperc = newperc;
  274.                   for (x=n; x<PCX_BPL; x+=n)
  275.                   {
  276.                      n = ReadByte(fin);
  277.                      if ((n & 0xC0) == 0xC0)
  278.                      {
  279.                         n &= 0x3F;
  280.                         b = ReadByte(fin);
  281.                         memset(ptr,b,n);
  282.                         ptr += n;
  283.                      }
  284.                      else
  285.                      {
  286.                         *ptr++ = n;
  287.                         n = 1;
  288.                      }
  289.                   }
  290.                   WriteIFFRow(fout,Buffer,IFF_BPL);
  291.                   ptr = Buffer;
  292.                   n = x-PCX_BPL;
  293.                   if (n > 0)
  294.                   {
  295.                      memset(ptr,b,n);
  296.                      ptr += n;
  297.                   }
  298.                }
  299.                BodySize = WriteSize - BodyPosition - 4;
  300.                if (BodySize & 1)
  301.                {
  302.                   WriteByte(fout,0);
  303.                   BodySize++;
  304.                }
  305.                fseek(fout,BodyPosition,0);
  306.                WriteLong(fout,BodySize);
  307.                fseek(fout,4,0);
  308.                WriteLong(fout,BodyPosition+BodySize-4);
  309.                printf ("Done!\n");
  310.                
  311.                return 0;
  312.             }
  313.             else
  314.                printf ("%%%% Unable to open %s for output as IFF file\n",argv[2]);
  315.          }
  316.          else
  317.             printf ("%%%% Invalid PCX file\n");
  318.       }
  319.       else
  320.          printf ("%%%% Unable to open %s for input from PCX file\n",argv[1]);
  321.    }
  322.    else
  323.       printf ("\nUsage:\n\n   PCXTOIFF <sourcepcxfile> <destifffile>\n\n");
  324.  
  325.    return 20;
  326. }
  327.